/**
 * @author 0283000115
 * @date 2018年6月21日-下午2:23:26
 */
package com.zte.claa.inficombo.csa.app.service.redis;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.DisposableBean;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Lazy;
import org.springframework.data.redis.listener.ChannelTopic;
import org.springframework.data.redis.listener.RedisMessageListenerContainer;
import org.springframework.stereotype.Service;

import com.zte.claa.inficombo.csa.app.config.RedisChannelProps;
import com.zte.claa.inficombo.csa.app.dao.mysql.impl.CameraPhotoDataMapper;
import com.zte.claa.inficombo.csa.app.model.dev.CmdModelBean;
import com.zte.claa.inficombo.csa.app.model.dev.DataModelBean;
import com.zte.claa.inficombo.csa.app.model.dev.DevBase;
import com.zte.claa.inficombo.csa.app.model.dev.DevTpExtData;
import com.zte.claa.inficombo.csa.app.model.dev.DevTypeBase;
import com.zte.claa.inficombo.csa.app.model.dev.DevTypeModel;
import com.zte.claa.inficombo.csa.app.model.dev.ResIndexDataModel;
import com.zte.claa.inficombo.csa.app.model.proj.ProjectDBPara;
import com.zte.claa.inficombo.csa.app.model.redis.AlarmCode;
import com.zte.claa.inficombo.csa.app.model.redis.DevExtData;
import com.zte.claa.inficombo.csa.app.model.redis.DevModelChgData;
import com.zte.claa.inficombo.csa.app.service.csa.impl.BaseCacheManager;
import com.zte.claa.inficombo.csa.app.service.persistent.CSADataPersistService;
import com.zte.claa.inficombo.csa.app.service.rptparse.ParserContainer;

/**
 * @author 0283000115
 *
 */

@Service("RedisMsgListenService")
@Lazy(false)
public class RedisMsgListenService implements InitializingBean, DisposableBean {
	private Logger logger = LoggerFactory.getLogger(RedisMsgListenService.class);
	
	@Autowired
	private RedisMessageListenerContainer listenerContainer;
	
	@Autowired
	private BaseCacheManager cacheManager;
	
	@Autowired 
	private CSADataPersistService persistService;
	
	@Autowired
	private RedisChannelProps channelProp;
	
	@Autowired
	private CameraPhotoDataMapper photoDataMapper;
	
	@Autowired
	private ParserContainer parserContainer;
	
	// web服务发布的model变更消息监听器.
	private WebModelChgListener modelChgListener;
	
	// AIC服务发布的识别结果消息监听器
	private AicRecogChgListener aicRecogChgListener;

	/* (non-Javadoc)
	 * @see org.springframework.beans.factory.InitializingBean#afterPropertiesSet()
	 */
	@Override
	public void afterPropertiesSet() throws Exception {
		// 2.注册各类消息主题监听器（告警监听器统一由告警池服务直接调用本服务接口方法，不再通过topic消息主题转发）
		this.modelChgListener = new WebModelChgListener(this);
		this.listenerContainer.addMessageListener(this.modelChgListener, new ChannelTopic(this.channelProp.getWebdevchgrptchannel().trim()));
		
		this.aicRecogChgListener = new AicRecogChgListener(this);
		this.listenerContainer.addMessageListener(this.aicRecogChgListener, new ChannelTopic(this.channelProp.getAicRecogResult().trim()));
	}
	
	/* (non-Javadoc)
	 * @see org.springframework.beans.factory.DisposableBean#destroy()
	 */
	@Override
	public void destroy() throws Exception {
		if(this.modelChgListener != null){
			this.listenerContainer.removeMessageListener(this.modelChgListener);
		}
		
		if(this.aicRecogChgListener != null){
			this.listenerContainer.removeMessageListener(this.aicRecogChgListener);
		}
		this.listenerContainer.destroy();
	}
	
	public void processCmdModelChg(CmdModelBean cmdModel, byte op) {
		String devTp = cmdModel.getTypeid();
		DevTypeModel dtModel = this.cacheManager.getDevTypeModel(devTp);
		if(dtModel == null){
			return;
		}
		switch(op){
		case DevModelChgData.OPFLAG_ADD:
		case DevModelChgData.OPFLAG_MOD:
			dtModel.addCmdModelBean(cmdModel);			
			break;
		case DevModelChgData.OPFLAG_DEL:
			dtModel.removeCmdModelBean(cmdModel);			
			break;
		}
		this.cacheManager.putDevTypeModel(dtModel);
		logger.info("process cmdmodelchg ok: op="+op+", msg="+cmdModel);
	}

	public void processDataModelChg(DataModelBean dm, byte op) {
		String devTp = dm.getTypeid();
		DevTypeModel dtModel = this.cacheManager.getDevTypeModel(devTp);
		if(dtModel == null){
			return;
		}
		switch(op){
		case DevModelChgData.OPFLAG_ADD:
		case DevModelChgData.OPFLAG_MOD:
			dtModel.addDataModelBean(dm);
			break;
		case DevModelChgData.OPFLAG_DEL:
			dtModel.removeDataModelBean(dm);
			break;
		}
		this.cacheManager.putDevTypeModel(dtModel);
		logger.info("process datamodelchg ok: op="+op+", msg="+dm);
	}
	
	public void processResIndexModelChg(ResIndexDataModel dm, byte op) {
		String devTp = dm.getTypeid();
		DevTypeModel dtModel = this.cacheManager.getDevTypeModel(devTp);
		if(dtModel == null){
			return;
		}
		switch(op){
		case DevModelChgData.OPFLAG_ADD:
		case DevModelChgData.OPFLAG_MOD:
			dtModel.addResIndexDataModel(dm);
			break;
		case DevModelChgData.OPFLAG_DEL:
			dtModel.removeResIndexDataModel(dm);
			break;
		}
		this.cacheManager.putDevTypeModel(dtModel);
		logger.info("process ResIndexDataModel ok: op="+op+", msg="+dm);
	}

	public void processDevChg(DevBase dev, byte op) {
		switch(op){
		case DevModelChgData.OPFLAG_ADD:
			this.cacheManager.putDev(dev);
			break;
		case DevModelChgData.OPFLAG_MOD:
			DevBase curdev = this.cacheManager.getDev(dev.getDevEui());
			if(curdev != null){
				dev.setDatajson(curdev.getDatajson());
			}
			this.cacheManager.putDev(dev);
			break;
		case DevModelChgData.OPFLAG_DEL:
			this.cacheManager.removeDev(dev.getDevEui());
			break;
		}
		logger.info("process devchg ok: op="+op+", msg="+dev);
	}
	
	/**
	 * Web侧devextdata变更时，同步修改CSA的devbase的datajson数据.
	 * @param devExtData
	 * @param op
	 */
	public void processDevExtDataChg(DevExtData devExtData, byte op) {
		DevBase dev = null;
		switch(op){
		case DevModelChgData.OPFLAG_ADD:
		case DevModelChgData.OPFLAG_MOD:
			dev = this.cacheManager.getDev(devExtData.getDeveui());
			if(dev != null){
				dev.setDatajson(devExtData.getDatajson());
				this.cacheManager.putDev(dev);
			}
			break;
		case DevModelChgData.OPFLAG_DEL:
			dev = this.cacheManager.getDev(devExtData.getDeveui());
			if(dev != null){
				dev.setDatajson("");
				this.cacheManager.putDev(dev);
			}
			break;
		}
		logger.info("process devExtDatachg ok: op="+op+", msg="+devExtData);
	}

	public void processDevTypeChg(DevTypeBase dtp, byte op) {
		String devTp = dtp.getTypeid();
		DevTypeModel dtModel = this.cacheManager.getDevTypeModel(devTp);
		if(dtModel == null){
			return;
		}
		switch(op){
		case DevModelChgData.OPFLAG_ADD:
		case DevModelChgData.OPFLAG_MOD:
			dtModel.setBase(dtp);
			this.cacheManager.putDevTypeModel(dtModel);
			break;
		case DevModelChgData.OPFLAG_DEL:
			this.cacheManager.reloadDevTypeModelDirect(devTp);
			break;
		}
		logger.info("process devtypechg ok: op="+op+", msg="+dtp);
	}

	public void processFmModelChg(AlarmCode fm, byte op) {
		switch(op){
		case DevModelChgData.OPFLAG_ADD:
		case DevModelChgData.OPFLAG_MOD:
			this.cacheManager.putAlarmCode(fm);
			break;
		case DevModelChgData.OPFLAG_DEL:
			this.cacheManager.removeAlarmCode(fm.getDevtype(), fm.getAlarmcode());
			break;
		}
	}
	
	/**
	 * projectdb对应的datasource有缓存，需要使其失效，以便重新获取.
	 * @param jsonData
	 * @param op
	 */
	public void processProjDBParaChg(ProjectDBPara dbpara, byte op) {
		String projectId = dbpara.getProjectid();
		this.persistService.invalidDataSource(projectId); 
		switch(op){
		case DevModelChgData.OPFLAG_ADD:
		case DevModelChgData.OPFLAG_MOD:
			this.cacheManager.putProjDBPara(dbpara);
			break;
		case DevModelChgData.OPFLAG_DEL:
			this.cacheManager.removeProjDBPara(projectId);
			break;
		}
		logger.info("process dbpara ok: op="+op+", msg="+dbpara);
	}
	
	/**
	 * 设备类型扩展属性变更处理.
	 * 
	 * @param dtpExt
	 * @param op
	 */
	public void processDevTpExtChg(DevTpExtData dtpExt, byte op) {
		switch(op){
		case DevModelChgData.OPFLAG_ADD:
		case DevModelChgData.OPFLAG_MOD:
			this.cacheManager.putDevTpExtData(dtpExt);
			break;
		case DevModelChgData.OPFLAG_DEL:
			this.cacheManager.removeDevTpExtData(dtpExt.getDevtpid());
			break;
		}
		logger.info("process devtpExtchg ok: op="+op+", msg="+dtpExt);
	}

	public BaseCacheManager getCacheManager() {
		return cacheManager;
	}

	public CameraPhotoDataMapper getPhotoDataMapper() {
		return photoDataMapper;
	}

	public ParserContainer getParserContainer() {
		return parserContainer;
	}
	
}
